﻿using debugger;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public class Base : Form
    {
        public bool fast = false;
        public void getVGA(byte[] data, uint pos)
        { 
        }

        [DllImport("CH341DLL.DLL")]
        public static extern uint CH341GetDrvVersion();

        [DllImport("CH341DLL.DLL")]
        public static extern uint CH341GetVersion();

        [DllImport("CH341DLL.DLL")]
        public static extern IntPtr CH341OpenDevice(uint iIndex);

        [DllImport("CH341DLL.DLL")]
        public static extern void CH341CloseDevice(uint iIndex);

        [DllImport("CH341DLL.DLL")]
        public static extern bool CH341Set_D5_D0(uint iIndex, uint iSetDirOut, uint iSetDataOut);

        [DllImport("CH341DLL.DLL")]
        public static extern bool CH341StreamSPI4(uint iIndex, uint iChipSelect, uint iLength, byte[] ioBuffer);

        [DllImport("CH341DLL.DLL")]
        public static extern bool CH341ResetDevice(uint iIndex);
        [DllImport("CH341DLL.DLL")]
        public static extern bool CH341SetStream(uint iIndex, uint iMode);

        [DllImport("CH341DLL.DLL")]
        public static extern bool CH341WriteData0(uint iIndex, byte[] iBuffer, ref uint ioLength);

        [DllImport("CH341DLL.DLL")]
        public static extern bool CH341WriteData1(uint iIndex, byte[] iBuffer, ref uint ioLength);

        [DllImport("CH341DLL.DLL")]
        public static extern bool CH341ReadData0(uint iIndex, byte[] oBuffer, ref uint ioLength);

        [DllImport("CH341DLL.DLL")]
        public static extern bool CH341ReadData1(uint iIndex, byte[] oBuffer, ref uint ioLength);
        [DllImport("CH341DLL.DLL")]
        public static extern bool CH341GetStatus(uint iIndex, ref uint iStatus);

        byte[] data = new byte[5];
        public bool connect()
        {
            IntPtr h = CH341OpenDevice(0);
            if (h.ToInt64() > 0)
            {
                //CH341ResetDevice(0);
                // 位1-位0: I2C接口速度/SCL频率, 00=低速/20KHz,01=标准/100KHz(默认值),10=快速/400KHz,11=高速/750KHz
                // 位2:     SPI的I/O数/IO引脚, 0=单入单出(D3时钟/D5出/D7入)(默认值),1=双入双出(D3时钟/D5出D4出/D7入D6入)
                // 位7:     SPI字节中的位顺序, 0=低位在前, 1=高位在前
                // 其它保留,必须为0
                //CH341SetStream(0, 0x83);
                CH341SetStream(0, 0x03);
                return true;
            }
            else
            {
                CH341CloseDevice(0);
                return false;
            }

        }
        private uint readFromPort()
        {
            uint val = 0;
            //D0 cs0
            //D1 cs1
            //D2 cs2
            //D3 sck
            //D4 nc
            //D5 mosi
            //D6 ack            //0x0080efb7            //0x0080eff7
            //D7 miso
            while ((val & 0x40) == 0)
            {
                bool a = CH341GetStatus(0, ref val);
                if (!a)
                {
                    throw new Exception();
                }
                //Console.WriteLine("wait");
            }
            data[0] = 0;
            data[1] = 0;
            data[2] = 0;
            data[3] = 0;
            data[4] = 0;
            // 片选控制, 位7为0则忽略片选控制, 位7为1则参数有效: 位1位0为00/01/10分别选择D0/D1/D2引脚作为低电平有效片选
            bool ret = CH341StreamSPI4(0, 0x80, 4, data);
            uint temp = 0;
            temp |= data[0];
            temp |= (uint)(data[1]<<8);
            temp |= (uint)(data[2]<<16);
            temp |= (uint)(data[3]<<24);
            return temp;
        }

        public uint sendCmdRet(byte cmd, uint? udata = null)
        {
            sendCmd(cmd, udata);
            uint val = 0;
            val = readFromPort();
            return val;
        }

        public void sendCmd(byte cmd, uint? udata = null)
        {
            bool ret;

            data[0] = cmd;
            if (udata != null)
            {
                data[1] = (byte)(udata & 0xFF);
                data[2] = (byte)((udata >> 8) & 0xFF);
                data[3] = (byte)((udata >> 16) & 0xFF);
                data[4] = (byte)((udata >> 24) & 0xFF);
                //Console.WriteLine(Util.getHex2(cmd) + "," + Util.getHex8(udata.Value));
            }
            else {
                //Console.WriteLine(Util.getHex2(cmd) );
            }
            // 片选控制, 位7为0则忽略片选控制, 位7为1则参数有效: 位1位0为00/01/10分别选择D0/D1/D2引脚作为低电平有效片选
            ret = CH341StreamSPI4(0, 0x80, 5, data);
        }

        public void receive(byte[] data)//read
        {
            bool ret;

            // 片选控制, 位7为0则忽略片选控制, 位7为1则参数有效: 位1位0为00/01/10分别选择D0/D1/D2引脚作为低电平有效片选
            ret = CH341StreamSPI4(0, 0x82, (uint)data.Length, data);
        }
        public void send(byte[] data)//write
        {
            bool ret;
            byte[] temp = new byte[data.Length];
            for (int i = 0; i < data.Length; i++)
            {
                temp[i] = data[i];
            }
            // 片选控制, 位7为0则忽略片选控制, 位7为1则参数有效: 位1位0为00/01/10分别选择D0/D1/D2引脚作为低电平有效片选
            ret = CH341StreamSPI4(0, 0x81, (uint)data.Length, temp);
        }

    }
}
